package com.itheima.reggie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.service.SetmealDishService;
import com.itheima.reggie.utils.RedisKeys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author mwj
 * @date 2021/11/24
 * @TIME:15:22
 */
@Service
@Slf4j
public class DishServciceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    //    @Autowired
//    private DishMapper dishMapper;
    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SetmealDishService setmealDishService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增菜品，同时保存对应的口味数据
     *
     * @param dishDto
     */
    @Transactional
    @Override
    public void addDish(DishDto dishDto) {
        //保存菜品的基本信息到菜品表dish
        //dishMapper.insert(dishDto);
        save(dishDto);
        Long id = dishDto.getId();//菜品id
        //菜品口味
        List<DishFlavor> flavors = dishDto.getFlavors();
//        flavors.stream().forEach(c -> c.setDishId(id));
        //todo map运用
        flavors = flavors.stream().map((c) -> {
            c.setDishId(id);
            return c;
        }).collect(Collectors.toList());
        dishFlavorService.saveBatch(flavors);
        //优化
        //redisTemplate.delete(RedisKeys.DISH + dishDto.getCategoryId() + "_" + dishDto.getStatus());


    }

    @Override
    public Page<DishDto> findByPage(Integer page, Integer pageSize, String name) {

        //1.构建分页对象
        IPage<Dish> ipage = new Page<>(page, pageSize);
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        if (null != name && name != "") {
            //添加模糊查询
            wrapper.like(Dish::getName, name);
        }
        //因为新的菜品应该放前面，所以需要添加一个排序规则
        //desc 从大到小
        wrapper.orderByDesc(Dish::getUpdateTime);
        //分页查询
        //展示未被逻辑删除的
        wrapper.eq(Dish::getIsDeleted, 0);
        IPage<Dish> page1 = this.page(ipage, wrapper);
        //把原有的Dish对象重新封装成一个DishDto对象
        List<Dish> dishes = page1.getRecords();

        //todo 视频对象拷贝
        //深克隆
        List<DishDto> dishDtos = JSON.parseArray(JSON.toJSONString(dishes), DishDto.class);
        //方法1：
//        dishDtos = dishDtos.stream().map((c) -> {
//            Long categoryId = c.getCategoryId();
//            Category category = categoryService.getById(categoryId);
//            c.setCategoryName(category.getName());
//            return c;
//        }).collect(Collectors.toList());
        //方法2：
        for (DishDto dishDto : dishDtos) {
            Long categoryId = dishDto.getCategoryId();//获得分类id
            //根据分类id 查询分类名称
            Category category = categoryService.getById(categoryId);
            //把分类的名字设置给dto对象
            dishDto.setCategoryName(category.getName());
        }

        Page<DishDto> dtoPage = new Page<>();
        dtoPage.setRecords(dishDtos);
        dtoPage.setTotal(page1.getTotal());

        return dtoPage;
    }

    @Override
    public DishDto findById(Long id) {

        Dish dish = this.getById(id);
        //获取菜品口味
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, id);
        List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper);
        //封装到dishdto
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish, dishDto);
        dishDto.setFlavors(dishFlavors);
        return dishDto;


    }

    @Override
    public void updateDishDto(DishDto dishDto) {
        //dish表修改
        this.updateById(dishDto);
        //flover表先删除后新增
        //先获得flavor
        List<DishFlavor> flavors = dishDto.getFlavors();
        //给flavor的dishid赋值  或者for循环
        //为每个口味设置菜品id
        flavors = flavors.stream().map((c) -> {
            c.setDishId(dishDto.getId());
            return c;
        }).collect(Collectors.toList());
        //增删改 使用lambdaUpdateWrapper//todo
        //删除
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, dishDto.getId());
        dishFlavorService.remove(wrapper);
        //再添加
        dishFlavorService.saveOrUpdateBatch(flavors);
        //删除当前菜品缓存  如果用户修改了菜品的分类，那么原来分类下将少一个菜品，新的分类下将多一个菜品
        //redisTemplate.delete(redisTemplate.keys(RedisKeys.DISH + "*"));
    }

    @Override
    public List<DishDto> findDishesByCategoryId(Long categoryId, Integer status) {

        //1.获取缓存中的数据
        //11.40
        //List<DishDto> list = (List<DishDto>) redisTemplate.opsForValue().get(RedisKeys.DISH + categoryId + "_" + status);

        //if (list == null) {
            LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Dish::getCategoryId, categoryId);
            wrapper.eq(Dish::getStatus, 1);
            List<Dish> dishes = this.list(wrapper);
            //把dish转换成dishdto
            String string = JSON.toJSONString(dishes);
            List<DishDto> dishDtos = JSON.parseArray(string, DishDto.class);
            //补全dishdto中的数据
            for (DishDto dishDto : dishDtos) {
                //封装口味信息
                //todo
                LambdaQueryWrapper<DishFlavor> flavorwrapper = new LambdaQueryWrapper<>();
                flavorwrapper.eq(DishFlavor::getDishId, dishDto.getId());
                List<DishFlavor> dishFlavors = dishFlavorService.list(flavorwrapper);
                if (dishFlavors.size() > 0) {
                    dishDto.setFlavors(dishFlavors);
                }
                //封装分类名
                Category category = categoryService.getById(dishDto.getCategoryId());
                if (category != null) {
                    dishDto.setCategoryName(category.getName());
                }
            }
            //如果不存在，需要查询数据库，将查询到的菜品数据缓存到
            //redisTemplate.opsForValue().set(RedisKeys.DISH + categoryId + "_" + status, dishDtos);
            return dishDtos;
        //}
        //如果存在，直接返回，无需查询数据库
//        System.out.println("redis缓存读取了");
//        return list;
    }


    //todo 删除缓存
    @Override
    public R deleteByIds(Long[] ids) {
        //需逻辑删除菜品表，菜品口味，如果是套餐内拒绝删除
        //如果是套餐内拒绝删除
        for (Long id : ids) {
            LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SetmealDish::getDishId, id);
            SetmealDish setmealDish = setmealDishService.getOne(wrapper);
            if (setmealDish != null && setmealDish.getIsDeleted() == 0) {
                //todo
                return R.error("有套餐包含此菜，无法删除");
            }
        }


        //1.先根据ids查询出全部dishes
        List<Dish> dishes = this.listByIds(Arrays.asList(ids));
        //2.遍历后更改isdelete为1
        dishes = dishes.stream().map(c -> {
            c.setIsDeleted(1);
            return c;
        }).collect(Collectors.toList());
        //3.修改
        this.updateBatchById(dishes);


        //4.需要删除彩票口味
        //4.1还是先根据dishid查出全部dishflavor
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(DishFlavor::getDishId, ids);
        List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper);
        dishFlavors = dishFlavors.stream().map(c -> {
            c.setIsDeleted(1);
            return c;
        }).collect(Collectors.toList());
        //5.修改
        dishFlavorService.updateBatchById(dishFlavors);
        return R.success("批量删除成功");
    }

    @Override
    public void statusByIds(Integer statusHandle, Long[] ids) {
        //先根据ids获取全部的dish
        List<Dish> dishes = this.listByIds(Arrays.asList(ids));
        //2.遍历，使status=dishstat
        dishes = dishes.stream().map(c -> {
            c.setStatus(statusHandle);
            return c;
        }).collect(Collectors.toList());
        //3.修改
        this.updateBatchById(dishes);
    }
}
